---
title: Relations
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Relations work a little differently in `mongoose` when compared to other relational ORMs such as `sequelize` or `typescript`. You can read more about relations (references) in `mongoose` [here](https://mongoosejs.com/docs/populate.html)

:::note
There are multiple ways to set of references in `mongoose` there are intended as starting point.
:::

:::warning
Filtering on references is not supported by mongoose.
:::

## One to Many/Many To One Example

To set up a one to many/many to one relationship in mongoose you will store a reference in your document

For example lets add sub tasks to our todo items by storing a `todoItem` ref on our `subTask`

<Tabs
  defaultValue="todoitem"
  values={[
    { label: 'TodoItemEntity', value: 'todoitem', },
    { label: 'SubTaskEntity', value: 'subtask', },
  ]
}>
<TabItem value="todoitem">


```ts title="todo-item/todo-item.entity.ts" {32-36}
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { SchemaTypes, Types, Document } from 'mongoose';

@Schema({ timestamps: true })
export class TodoItemEntity extends Document {
  @Prop({ required: true })
  title!: string;

  @Prop()
  description?: string;

  @Prop({ required: true })
  completed!: boolean;

  @Prop({ default: Date.now })
  createdAt!: Date;

  @Prop({ default: Date.now })
  updatedAt!: Date;

  @Prop({ default: 0 })
  priority!: number;

  @Prop()
  createdBy?: string;

  @Prop()
  updatedBy?: string;
}

export const TodoItemEntitySchema = SchemaFactory.createForClass(TodoItemEntity);
TodoItemEntitySchema.virtual('subTasks', {
  ref: 'SubTaskEntity',
  localField: '_id',
  foreignField: 'todoItem',
});
```

</TabItem>
<TabItem value="subtask">

```ts title="sub-task/sub-task.entity.ts" {15-16}
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { SchemaTypes, Types, Document } from 'mongoose';

@Schema({ timestamps: true })
export class SubTaskEntity extends Document {
  @Prop({ required: true })
  title!: string;

  @Prop()
  description?: string;

  @Prop({ required: true })
  completed!: boolean;

  @Prop({ type: SchemaTypes.ObjectId, ref: 'TodoItemEntity', required: true })
  todoItem!: Types.ObjectId;

  @Prop()
  createdAt!: Date;

  @Prop()
  updatedAt!: Date;

  @Prop()
  createdBy?: string;

  @Prop()
  updatedBy?: string;
}

export const SubTaskEntitySchema = SchemaFactory.createForClass(SubTaskEntity);

```

</TabItem>
</Tabs>

Now that we have the relationship defined we can add the `@Relation` and `@CursorConnection` to our DTOs

<Tabs
  defaultValue="todoitem"
  values={[
    { label: 'TodoItemDTO', value: 'todoitem', },
    { label: 'SubTaskDTO', value: 'subtask', },
  ]
}>
<TabItem value="todoitem">

```ts title="todo-item/todo-item.dto.ts"
import { FilterableField, IDField, KeySet, CursorConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql';
import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto';

@ObjectType('TodoItem')
@KeySet(['id'])
// disable the remove because mongoose does not support removing a virtual
@CursorConnection('subTasks', () => SubTaskDTO, { disableRemove: true })
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField({ nullable: true })
  description?: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  createdAt!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updatedAt!: Date;

  @Field()
  age!: number;

  @FilterableField()
  priority!: number;

  @FilterableField({ nullable: true })
  createdBy?: string;

  @FilterableField({ nullable: true })
  updatedBy?: string;
}

```

</TabItem>
<TabItem value="subtask">

```ts title="sub-task/sub-task.dto.ts"
import { FilterableField, IDField, KeySet, Relation } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { TodoItemDTO } from '../../todo-item/dto/todo-item.dto';

@ObjectType('SubTask')
@KeySet(['id'])
// disable the remove because a sub task cannot exist without a todoitem
@Relation('todoItem', () => TodoItemDTO, { disableRemove: true })
export class SubTaskDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField({ nullable: true })
  description?: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  createdAt!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updatedAt!: Date;

  @FilterableField({ nullable: true })
  createdBy?: string;

  @FilterableField({ nullable: true })
  updatedBy?: string;
}

```

</TabItem>
</Tabs>

## Many To Many Example

In this example we'll add `tags` to `todoItems` by storing an array of `tag` references on the `todoItems`.

<Tabs
  defaultValue="todoitem"
  values={[
    { label: 'TodoItemEntity', value: 'todoitem', },
    { label: 'TagEntity', value: 'tag', },
  ]
}>
<TabItem value="todoitem">

```ts title="todo-item/todo-item.entity.ts" {21-23}
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { SchemaTypes, Types, Document } from 'mongoose';

@Schema({ timestamps: true })
export class TodoItemEntity extends Document {
  @Prop({ required: true })
  title!: string;

  @Prop()
  description?: string;

  @Prop({ required: true })
  completed!: boolean;

  @Prop({ default: Date.now })
  createdAt!: Date;

  @Prop({ default: Date.now })
  updatedAt!: Date;

  // notice the brackets around the prop options
  @Prop([{ type: SchemaTypes.ObjectId, ref: 'TagEntity' }])
  tags!: Types.ObjectId[];

  @Prop({ default: 0 })
  priority!: number;

  @Prop()
  createdBy?: string;

  @Prop()
  updatedBy?: string;
}

export const TodoItemEntitySchema = SchemaFactory.createForClass(TodoItemEntity);
```

</TabItem>
<TabItem value="tag">

```ts title="tag/tag.entity.ts" {23-27}
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

@Schema({ timestamps: true })
export class TagEntity extends Document {
  @Prop({ required: true })
  name!: string;

  @Prop()
  createdAt!: Date;

  @Prop()
  updatedAt!: Date;

  @Prop()
  createdBy?: string;

  @Prop()
  updatedBy?: string;
}

export const TagEntitySchema = SchemaFactory.createForClass(TagEntity);
TagEntitySchema.virtual('todoItems', {
  ref: 'TodoItemEntity',
  localField: '_id',
  foreignField: 'tags',
});

```

</TabItem>
</Tabs>

Now that we have the relationship defined we can add the `@CursorConnection` to our DTOS

<Tabs
  defaultValue="todoitem"
  values={[
    { label: 'TodoItemDTO', value: 'todoitem', },
    { label: 'TagDTO', value: 'tag', },
  ]
}>
<TabItem value="todoitem">

```ts title="todo-item/todo-item.dto.ts"
import { FilterableField, IDField, KeySet, CursorConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql';
import { TagDTO } from '../../tag/dto/tag.dto';

@ObjectType('TodoItem')
@KeySet(['id'])
@CursorConnection('tags', () => TagDTO)
export class TodoItemDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  title!: string;

  @FilterableField({ nullable: true })
  description?: string;

  @FilterableField()
  completed!: boolean;

  @FilterableField(() => GraphQLISODateTime)
  createdAt!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updatedAt!: Date;

  @Field()
  age!: number;

  @FilterableField()
  priority!: number;

  @FilterableField({ nullable: true })
  createdBy?: string;

  @FilterableField({ nullable: true })
  updatedBy?: string;
}
```

</TabItem>
<TabItem value="tag">

```ts title="tag/tag.dto.ts"
import { FilterableField, IDField, KeySet, CursorConnection } from '@nestjs-query/query-graphql';
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql';
import { TodoItemDTO } from '../../todo-item/dto/todo-item.dto';

@ObjectType('Tag')
@KeySet(['id'])
// disable update and remove since it is a virtual in the entity
@CursorConnection('todoItems', () => TodoItemDTO, { disableUpdate: true, disableRemove: true })
export class TagDTO {
  @IDField(() => ID)
  id!: string;

  @FilterableField()
  name!: string;

  @FilterableField(() => GraphQLISODateTime)
  createdAt!: Date;

  @FilterableField(() => GraphQLISODateTime)
  updatedAt!: Date;

  @FilterableField({ nullable: true })
  createdBy?: string;

  @FilterableField({ nullable: true })
  updatedBy?: string;
}
```

</TabItem>
</Tabs>




